package com.douqu.game.battle.entity.aobject;

import com.bean.core.util.Utils;
import com.douqu.game.battle.controller.BattleController;
import com.douqu.game.battle.controller.sprite.PlayerController;
import com.douqu.game.battle.controller.sprite.SpriteController;
import com.douqu.game.battle.entity.BattleSkill;
import com.douqu.game.battle.entity.BuffBox;
import com.douqu.game.battle.entity.tmp.SpriteBattleTmp;
import com.douqu.game.battle.util.BattleUtils;
import com.douqu.game.core.astar.AbsCoord;
import com.douqu.game.core.astar.ObjectBound;
import com.douqu.game.core.config.ProfessionConfig;
import com.douqu.game.core.config.battle.BuffConfig;
import com.douqu.game.core.config.battle.SkillConfig;
import com.douqu.game.core.config.common.Position;
import com.douqu.game.core.config.sprite.MasterConfig;
import com.douqu.game.core.config.sprite.SoldierConfig;
import com.douqu.game.core.config.sprite.Sprite;
import com.douqu.game.core.config.talent.TalentUpConfig;
import com.douqu.game.core.e.E_Attribute;
import com.douqu.game.core.e.E_BattleAObjectStatus;
import com.douqu.game.core.entity.battle.SpriteTemp;
import com.douqu.game.core.entity.common.TwoTuple;
import com.douqu.game.core.entity.ext.data.major.TalentBean;
import com.douqu.game.core.factory.ConstantFactory;
import com.douqu.game.core.factory.DataFactory;
import com.douqu.game.core.protobuf.SGCommonProto;
import com.douqu.game.core.util.LogUtils;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 战斗中的对象
 * Created by bean on 2017/7/27.
 */
public class BattleAObject {

    protected int uniqueId;

    /**
     * 所属主人
     */
    public SpriteController masterController;

    public BattleController battleController;

    protected E_BattleAObjectStatus status;

    /**
     * 对应的作战基本对象
     */
    protected Sprite sprite;


    /**
     * 等级
     */
    protected int lv;

    /**
     * 星级
     */
    protected int star;

    protected int fc;

    protected long hp;

    protected long maxHp;

    /**
     * BOSS战的时候每次缓存战斗开始时的生命
     */
    protected long cacheMaxHp;

    /**
     * 对敌人造成的总伤害
     */
    protected long damage;

    /** 攻击 */
    public BattleAtt atk;
    /** 物理防御 */
    public BattleAtt def;
    /** 力量 */
    protected BattleAtt power;
    /** 物理抗 */
    protected BattleAtt phyRes;
    /** 敏捷 */
    protected BattleAtt agility;
    /** 穿刺抗 */
    protected BattleAtt punRes;
    /** 智力 */
    protected BattleAtt wisdom;
    /** 魔法抗 */
    protected BattleAtt magRes;
    /** 暴击率(万分比) */
    protected BattleAtt cri;
    /** 抗暴率(万分比) */
    protected BattleAtt rec;
    /** 增伤率(万分比) */
    protected BattleAtt add;
    /** 免伤率(万分比) */
    protected BattleAtt exd;
    /** 命中率(万分比) */
    protected BattleAtt hit;
    /** 闪避率(万分比) */
    protected BattleAtt eva;
    /** 移动速度 */
    public BattleAtt moveSpeed;
    /** 攻击速度 */
    protected BattleAtt attackSpeed;

    protected BattleSkill[] skills;

    protected BattleSkill defaultSkill;

    protected int teamNo;

    /**
     * 出生点
     */
    public Position bornPoint;
    /** 所在的路线 */
    public int bornRoute;
    /**
     * 位置
     */
    public Position position;

    /**
     * 格子对象
     */
    protected ObjectBound objectBound;

    /**
     * 是否可穿越
     */
    protected boolean isFree = false;

    public BuffBox buffBox;

    /**
     * 前进的目标
     */
    protected BattleAObject goTarget;

    protected Position goTargetPosition;

    /**
     * 寻路的目标的原始点
     * key: 唯一ID
     * value: 寻路时目标所在的位置
     */
    protected Map<Integer, Position> goTargetOriginalPosMap;

    /**
     * 上一次攻击敌人的时间
     */
    protected long atkTime;

    /**
     * 是否能行走
     */
    public boolean isMove = false;

    /**
     * 是否触发冲锋
     */
    protected boolean isTriggerToAttack = false;

    /**
     * 上一次同步位置
     */
    public LastSendPosition lastSendPos;

    /**
     * 是否是默认拥有的战斗单位
     * 召唤出来的不算
     *
     */
    protected boolean isInitObject = true;

    /**
     * 通知主服务器的数据
     */
    protected SpriteTemp spriteTemp;


    public BattleAObject(SpriteController masterController, Sprite sprite, int uniqueId, int teamNo, Position position)
    {
        this.uniqueId = uniqueId;
        this.sprite = sprite;
        this.teamNo = teamNo;
        this.masterController = masterController;
        if(masterController.getBattleController() != null)
        {
            this.battleController = masterController.getBattleController();
        }
        else
        {
            LogUtils.error("BattleAObject Init Error: parent is not BattleController!" + masterController.getBattleController());
        }

        objectBound = new ObjectBound(sprite.gridArea);
        setPosition(position);

        this.buffBox = new BuffBox(battleController, this);
        this.status = E_BattleAObjectStatus.FREE;

        goTargetOriginalPosMap = new ConcurrentHashMap<>();

    }


    public void update(long currentTime)
    {
        defaultSkill.update();

        for(BattleSkill skill : skills)
        {
            skill.update();
        }

        buffBox.update(currentTime);
    }

    public void checkAISkill(int battleTime)
    {

    }



    public BattleSkill getReleaseSkill(long currentTime)
    {
        return null;
    }

    /**
     * 是否寻路同一个点
     * @param target
     * @return
     */
    public boolean isSameGoPosition(Position target)
    {
        return goTargetPosition != null && goTargetPosition.isSame(target);
    }
    /**
     * 是否是同一个目标对象
     * @param target
     * @return
     */
    public boolean isSameGoTarget(BattleAObject target)
    {
        if(goTarget == null || target == null || goTargetPosition == null)
            return false;

        return goTarget.uniqueId == target.uniqueId && !battleController.getAstar().getAstarMap().isObstacleToApplication(goTargetPosition.x, goTargetPosition.y);
    }

    protected void clearGoTarget()
    {
        if(goTarget != null)
        {
            this.goTargetOriginalPosMap.remove(goTarget.uniqueId);
            this.goTarget = null;
            this.goTargetPosition = null;
        }
    }


    protected void setDefaultAtk(BattleAObject target)
    {
        this.status = E_BattleAObjectStatus.BATTLING;

        defaultSkill.setDefaultAtkTarget(target);
//        LogUtils.debug("设置默认攻击目标:" + target);
        clearGoTarget();
    }


    protected void checkDefaultAtk()
    {
        BattleAObject defaultTarget = defaultSkill.getDefaultAtkTarget();
        if(defaultTarget == null)
            return;

        if(defaultTarget.isDie())
        {
            defaultSkill.clearDefaultAtkTarget();
            this.status = E_BattleAObjectStatus.FREE;
        }
    }


    public long getBaseAtt(int key)
    {
        if(E_Attribute.ATK.getCode() == key)
            return atk.base;
        else if(E_Attribute.DEF.getCode() == key)
            return def.base;
        else if(E_Attribute.HP.getCode() == key)
            return hp;
        else if(E_Attribute.CRI.getCode() == key)
            return cri.base;
        else if(E_Attribute.REC.getCode() == key)
            return rec.base;
        else if(E_Attribute.ADD.getCode() == key)
            return add.base;
        else if(E_Attribute.EXD.getCode() == key)
            return exd.base;
        else if(E_Attribute.HIT.getCode() == key)
            return hit.base;
        else if(E_Attribute.EVA.getCode() == key)
            return eva.base;
        else if(E_Attribute.POWER.getCode() == key)
            return power.base;
        else if(E_Attribute.WISDOM.getCode() == key)
            return wisdom.base;
        else if(E_Attribute.AGILITY.getCode() == key)
            return agility.base;
        else if(E_Attribute.MOVE_SPEED.getCode() == key)
            return moveSpeed.base;
        else if(E_Attribute.ATTACK_SPEED.getCode() == key)
            return attackSpeed.base;

        return 0;
    }

    public void setAttPlus(int key, int value)
    {
        if(E_Attribute.ATK.getCode() == key)
            atk.setPlus(value);
        else if(E_Attribute.DEF.getCode() == key)
            def.setPlus(value);
        else if(E_Attribute.CRI.getCode() == key)
            cri.setPlus(value);
        else if(E_Attribute.REC.getCode() == key)
            rec.setPlus(value);
        else if(E_Attribute.ADD.getCode() == key)
            add.setPlus(value);
        else if(E_Attribute.EXD.getCode() == key)
            exd.setPlus(value);
        else if(E_Attribute.HIT.getCode() == key)
            hit.setPlus(value);
        else if(E_Attribute.EVA.getCode() == key)
            eva.setPlus(value);
        else if(E_Attribute.POWER.getCode() == key)
            power.setPlus(value);
        else if(E_Attribute.WISDOM.getCode() == key)
            wisdom.setPlus(value);
        else if(E_Attribute.AGILITY.getCode() == key)
            agility.setPlus(value);
        else if(E_Attribute.MOVE_SPEED.getCode() == key)
        {
            moveSpeed.setPlus(value);
            stopMove();
        }
        else if(E_Attribute.ATTACK_SPEED.getCode() == key)
        {
            attackSpeed.setPlus(-value);
        }
    }


    public void addAtt(int key, int value)
    {
        if(value == 0)
            return;

       if(E_Attribute.ATK.getCode() == key)
           atk.addPlus(value);
       else if(E_Attribute.DEF.getCode() == key)
           def.addPlus(value);
       else if(E_Attribute.CRI.getCode() == key)
           cri.addPlus(value);
       else if(E_Attribute.REC.getCode() == key)
           rec.addPlus(value);
       else if(E_Attribute.ADD.getCode() == key)
           add.addPlus(value);
       else if(E_Attribute.EXD.getCode() == key)
           exd.addPlus(value);
       else if(E_Attribute.HIT.getCode() == key)
           hit.addPlus(value);
       else if(E_Attribute.EVA.getCode() == key)
           eva.addPlus(value);
       else if(E_Attribute.POWER.getCode() == key)
           power.addPlus(value);
       else if(E_Attribute.WISDOM.getCode() == key)
           wisdom.addPlus(value);
       else if(E_Attribute.AGILITY.getCode() == key)
           agility.addPlus(value);
       else if(E_Attribute.MOVE_SPEED.getCode() == key)
       {
           moveSpeed.addPlus(value);
           stopMove();
       }
       else if(E_Attribute.ATTACK_SPEED.getCode() == key)
       {
           attackSpeed.addPlus(-value);
       }
    }


    public long addHP(long value)
    {
        if(isDie())
            return 0;
        
        long before = hp;

        hp += value;
        hp = hp < 0 ? 0 : hp;
        hp = hp > maxHp ? maxHp : hp;

        if(spriteTemp != null) spriteTemp.setHp(hp);

        checkTypeSkill(ConstantFactory.SKILL_TYPE_HP_RATE, before, hp);

        if(isDie())
            masterController.getAttachment().getTargetBattleTmp().killEnemy();

        return hp - before;
    }

    /**
     * 获取伤害值
     * @param target
     * @return
     */
    public TwoTuple<SGCommonProto.E_DAMAGE_TYPE, Long> getDamage(BattleAObject target, SkillConfig skillConfig)
    {

        //一般情况下，伤害值 =[（攻击方最终攻击力-防御方最终防御力）*技能系数+技能基础伤害 ] *[ 1+（攻击方复合属性-防御方复合属性）*0.001 ] *（1+增伤率-免伤率+攻击方职业相克增伤系数-防御方职业相克免伤系）
        //如果是 skillConfig 表的 effectType 为 14 时，伤害值=（防御方生命上限 * 技能系数 - 防御方最终防御力 + 技能基础伤害）*[ 1+（攻击方复合属性-防御方复合属性）*0.005 ] *（1+增伤率-免伤率）
        //攻击方最终攻击力=初始攻击力+（等级-1）*攻击成长+装备强化+装备进阶+法宝强化+法宝进阶+英雄突破
        //防御方最终防御力=初始防御力+（等级-1）*防御成长+装备强化+装备进阶+法宝强化+法宝进阶+英雄突破
        //闪避的计算：在攻击之前先判定是否闪避，如果闪避则不计算伤害。直接显示“闪避”。闪避判定规则：攻方命中>守方闪避,则必然命中。攻方命中<守方闪避，则守方闪避-攻方命中=实际闪避率
        //暴击的计算：如果判定暴击，则在伤害计算后，给予双倍伤害。并且会显示“暴击”+具体数值的红字显示。暴击判定规则跟闪避一样，只是对抗属性为抗暴率
        //攻击方最终攻击力根据技能的效果类型来定
        //防御方最终防御力根据技能的效果类型来定
        //攻击方复合属性：物理攻击->力量，穿刺攻击->敏捷，魔法攻击->智力
        //防御方复合属性：根据攻击方的攻击类型业取值，取值方式同上
        //技能系数：技能里的ratio值
        //技能等级：技能是有成长体系的，会升级
//LogUtils.debug("计算伤害 -> 攻击方:" + detailInfo());
//        LogUtils.debug("计算伤害 -> 防御方:" + target.detailInfo());
        int evaValue = (int)(target.eva.getAtt() - hit.getAtt());
        if(evaValue > 0 && Utils.checkRandom(10000, evaValue))
        {
            LogUtils.debug("闪避成功 -> 攻击方:" + this + " 防御方:" + target);
            return new TwoTuple<>(SGCommonProto.E_DAMAGE_TYPE.DAMAGE_TYPE_MISS, 0l);
        }

        //（攻击方最终攻击力-防御方最终防御力）* 技能系数
        float temp1 = 0f;
        if(skillConfig.effectType == ConstantFactory.SKILL_EFFECT_TYPE_DAMAGE_TARGET_MAX_HP_RATE)
        {
            temp1 = target.maxHp * skillConfig.coefficient - target.def.getAtt();
        }
        else
        {
            temp1 = (getFinalAtk(skillConfig) - target.def.getAtt()) * skillConfig.coefficient;
        }
        LogUtils.debug("getFinalAtk(skillConfig):" + getFinalAtk(skillConfig) + " target.def.getAtt():" + target.def.getAtt() + " skillConfig.coefficient:" + skillConfig.coefficient);
        LogUtils.debug("temp1:" + temp1);
        temp1 = temp1 < temp1 * 0.05 ? (float) (temp1 * 0.05) : temp1;
        //(攻击方复合属性-防御方复合属性)，若< -100 则= -100
        long extAtt = getAtkExtAttr() - target.getDefExtAttr(this);
        LogUtils.debug("extAtt:" + extAtt);
        extAtt = extAtt < -100 ? -100 : extAtt;
        float temp = (float) ((temp1 + skillConfig.effectValue[0]) * (1 + extAtt * 0.001));
        LogUtils.debug("temp:" + temp);
        long result = (long) Math.ceil(temp);
        LogUtils.debug("result:" + result);
        float damagePlus = getDamagePlus(target) + 1;
        LogUtils.debug("damagePlus:" + damagePlus);
        damagePlus = damagePlus < 0.1f ? 0.1f : damagePlus;//1+增伤比-免伤比 不能小于0.1
        result = (long)(result * damagePlus);
        long min = (long) (atk.getAtt() * 0.1);
        LogUtils.debug("min:" + min + "  atk:" + atk.getAtt());
        result = result < min ? min : result;//最终伤害值不能小于攻击方攻击的10%
        LogUtils.debug("result:" + result);
        SGCommonProto.E_DAMAGE_TYPE damageType = SGCommonProto.E_DAMAGE_TYPE.DAMAGE_TYPE_DEFAULT;
        if(isTriggerToAttack)
        {
            isTriggerToAttack = false;

            LogUtils.debug("冲锋暴击成功 ->  攻击方:" + this + " 防御方:" + target);
            damageType = SGCommonProto.E_DAMAGE_TYPE.DAMAGE_TYPE_CRIT;
            result *= 2;
        }
        else if(Utils.checkRandom(10000, (int)(cri.getAtt() - target.rec.getAtt())))
        {
            LogUtils.debug("暴击成功 ->  攻击方:" + this + " 防御方:" + target + " 暴击率:" + cri.getAtt() + " 抗暴率:" + target.rec.getAtt());
            damageType = SGCommonProto.E_DAMAGE_TYPE.DAMAGE_TYPE_CRIT;
            result *= 2;
        }

        LogUtils.debug("result:" + result);

        if(masterController instanceof PlayerController)
        {
            //玩家的要计算天赋加成
            if(skillConfig.talentAddType != 0)
            {
                long talentAddValue = 0;
                TalentUpConfig talentUpConfig = null;
                Map<Integer, List<TalentBean>> talentMap = ((PlayerController) masterController).getPlayer().getTalentData().getTalentLibraryMap();
                for(List<TalentBean> list : talentMap.values())
                {
                    for(TalentBean talentBean : list)
                    {
                        talentUpConfig = talentBean.getConfig();
                        if(talentUpConfig != null && talentUpConfig.skill == skillConfig.talentAddType)
                        {
                            talentAddValue += talentUpConfig.getAddValue(result);
                            LogUtils.debug("天赋 -> " + talentUpConfig.getName() + "(" + talentBean.getTalentId() + ") 伤害加成，总加成:" + talentAddValue);
                        }
                    }
                }
                result += talentAddValue;
                LogUtils.debug("添加天赋伤害加成后的值 -> " + result);
            }
        }

        return new TwoTuple<>(damageType, result);
    }

    public long getFinalAtk(SkillConfig skillConfig)
    {
        switch (skillConfig.effectType)
        {
            case ConstantFactory.SKILL_EFFECT_TYPE_DAMAGE_ATK:
            case ConstantFactory.SKILL_EFFECT_TYPE_ABSORB_HP:
                return atk.getAtt();
            case ConstantFactory.SKILL_EFFECT_TYPE_DAMAGE_DEF:
                return def.getAtt();
            case ConstantFactory.SKILL_EFFECT_TYPE_DAMAGE_MAX_HP:
                return maxHp;
        }
        return 0;
    }


    /**
     * 获取加血的值
     * @param skillConfig
     * @return
     */
    public int getAddHP(SkillConfig skillConfig)
    {
        //加血值=施法者攻击力*技能系数+技能基础加血
        if(skillConfig.effectType == ConstantFactory.SKILL_EFFECT_TYPE_ADD_HP_ATK)
        {
            float temp = atk.getAtt() * skillConfig.coefficient + skillConfig.effectValue[0];
            return (int) temp;
        }

        return 0;
    }

    /**
     *
     * 增伤率-免伤率+攻击方职业相克增伤系数-防御方职业相克免伤系
     * @param target
     * @return
     */
    public float getDamagePlus(BattleAObject target)
    {
        ProfessionConfig professionConfig = DataFactory.getInstance().getGameObject(DataFactory.PROFESSION_KEY, sprite.profession);
        long damagePlus = add.getAtt();
        LogUtils.debug("damagePlus -> " + damagePlus);
        damagePlus += professionConfig.getDamagePlus(target.getSprite().profession);

        LogUtils.debug("damagePlus -> " + damagePlus);

        damagePlus += buffBox.getDamagePlus(target.getSprite());
        LogUtils.debug("damagePlus -> " + damagePlus);
        ProfessionConfig targetProfessionConfig = DataFactory.getInstance().getGameObject(DataFactory.PROFESSION_KEY, target.getSprite().profession);
        long targetExdamagePlus = target.exd.getAtt();
        LogUtils.debug("targetExdamagePlus -> " + targetExdamagePlus);
        targetExdamagePlus += targetProfessionConfig.getExdamagePlus(sprite.profession);
        LogUtils.debug("targetExdamagePlus -> " + targetExdamagePlus);
        //获取BUFF免疫值
        targetExdamagePlus += target.buffBox.getExdamagePlus(sprite);
        LogUtils.debug("targetExdamagePlus -> " + targetExdamagePlus);
        return (float) ((damagePlus - targetExdamagePlus) * 0.0001);
    }



    /**
     * 获取作为攻击方的复合属性
     * @return
     */
    public long getAtkExtAttr()
    {
        SpriteBattleTmp spriteBattleTmp = masterController.getAttachment();
        if(sprite.profession == ConstantFactory.PROFESSION_WARRIOR)
            return spriteBattleTmp.masterSoldier.power.getAtt();

        if(sprite.profession == ConstantFactory.PROFESSION_ARCHER)
            return spriteBattleTmp.masterSoldier.agility.getAtt()        ;

        if(sprite.profession == ConstantFactory.PROFESSION_ENCHANTER)
            return spriteBattleTmp.masterSoldier.wisdom.getAtt();

        return 0;
    }

    /**
     * 获取作为防御方的复合属性
     * @return
     */
    public long getDefExtAttr(BattleAObject attacker)
    {
        SpriteBattleTmp spriteBattleTmp = masterController.getAttachment();
        if(attacker.getSprite().profession == ConstantFactory.PROFESSION_WARRIOR)
            return spriteBattleTmp.masterSoldier.phyRes.getAtt();

        if(attacker.getSprite().profession == ConstantFactory.PROFESSION_ARCHER)
            return spriteBattleTmp.masterSoldier.punRes.getAtt();

        if(attacker.getSprite().profession == ConstantFactory.PROFESSION_ENCHANTER)
            return spriteBattleTmp.masterSoldier.magRes.getAtt();

        return 0;
    }



    /**
     * 前进
     */
    public void go()
    {
           //在子类实现
    }

    /**
     * 停止移动
     */
    public void stopMove()
    {
        //在子类实现
    }

    public boolean checkCanAtk(BattleAObject target)
    {
        return false;
    }


//    /**
//     * 检测攻击目标
//     * @param targetList
//     * @return
//     */
//    public TwoTuple<BattleAObject, BattleAObject> checkDefaultSkillTarget(List<BattleAObject> targetList)
//    {
//        //在子类实现
//        return null;
//    }

    /**
     * 获取普通攻击目标
     * @return
     */
    public BattleAObject getDefaultSkillTarget()
    {
        if(this instanceof BattleSoldierAObject)
        {
            BattleAObject targetMaster = masterController.getAttachment().getTargetBattleTmp().getMasterSoldier();
            if (defaultSkill.checkUnitType(targetMaster) && BattleUtils.isInAtkRange(this, targetMaster, defaultSkill.getSkillConfig()) && !targetMaster.isDie())
                return targetMaster;
        }

        List<BattleAObject> tempList = new CopyOnWriteArrayList<>();
        tempList.addAll(masterController.getAttachment().getTargetBattleTmp().getSoldierList());
        if(tempList.isEmpty())
            return null;

        if(tempList.size() > 1)
        {
            //按照离我的距离排序,最近的排在前面
            Collections.sort(tempList, new Comparator<BattleAObject>() {
                @Override
                public int compare(BattleAObject o1, BattleAObject o2) {
                    return new Float(BattleUtils.getDistance(position, o1.position)).compareTo(BattleUtils.getDistance(position, o2.position));
                }
            });
        }

        for(BattleAObject battleAObject : tempList)
        {
            if (!defaultSkill.checkUnitType(battleAObject))
                continue;

            if(battleAObject.isDie())
                continue;

            if(BattleUtils.isInAtkRange(this, battleAObject, defaultSkill.getSkillConfig()))
                return battleAObject;
        }
        return null;
    }



    public boolean checkDefaultSkillTarget(long currentTime)
    {
        return false;
    }

    public void checkFindRoute(){}


    /**
     * 获取到目标的路线
     * @param target
     */
    public void checkRoute(BattleAObject target)
    {

    }

    /**
     * 是否能克制对方
     * @param target
     * @return
     */
    public boolean isRestrict(BattleAObject target)
    {
        return sprite.isRestrict(target.getSprite());
    }



    public BattleSkill getSkill(int skillId)
    {
        for(BattleSkill skill : skills)
        {
            if(skill.getId() == skillId)
                return skill;
        }
        return null;
    }


    /**
     * 根据类型检测技能是否能释放
     * @param type
     */
    public boolean checkTypeSkill(int type, Object...params)
    {
        if(type != ConstantFactory.SKILL_TYPE_DIE && isDie())
            return false;

        if(isSilence() || !isCanAtk())
        {
            //被沉默或眩晕了，不能发动攻击
            return false;
        }

        boolean result = false;
        for(BattleSkill skill : skills)
        {
            if(skill.getSkillConfig().type == type)
            {
                if(!skill.isCanRelease())
                    continue;

                if(masterController.getAttachment().getCurCrystal() < skill.getSkillConfig().crystal)
                    continue;

                if(type == ConstantFactory.SKILL_TYPE_HP_RATE)
                {
                    long beforeHp = (long)params[0];
                    long curHp = (long)params[1];
                    int rateHp =(int)( maxHp * skill.getSkillConfig().typeParam / 10000);
                    if(!(beforeHp >= rateHp && curHp < rateHp))
                        continue;
                }
                if(skill.release())
                {
                    result = true;
                }
            }
        }
        return result;
    }





    /**
     * 获取损失的HP
     * @return
     */
    public long getLossHp()
    {
        return maxHp - hp;
    }


    /**
     * 是否可以行走
     * @return
     */
    public boolean isCanGo()
    {
        return buffBox.isCanGo();
    }

    /**
     * 是否可以攻击
     * @return
     */
    public boolean isCanAtk()
    {
        return buffBox.isCanAtk();
    }

    public boolean isSilence()
    {
        return buffBox.isSilence();
    }

    public void addBuff(BattleAObject releaser, BuffConfig buffConfig, SkillConfig skillConfig, String skillKey)
    {
        if(skillConfig.type != ConstantFactory.SKILL_TYPE_DIE && releaser.isDie())
            return;

        buffBox.addBuff(releaser, buffConfig, skillConfig.id, skillKey);
    }




    public int getRoute()
    {
        return ConstantFactory.ROUTE_TOP;
    }



    public SGCommonProto.BattleUnit.Builder parseBattleUnit(String... names)
    {
        SGCommonProto.BattleUnit.Builder data = SGCommonProto.BattleUnit.newBuilder();

        //一般是主将才有
        SGCommonProto.PlayerBaseInfo.Builder baseInfo = SGCommonProto.PlayerBaseInfo.newBuilder();
        if(sprite instanceof MasterConfig)
        {
            data.setBattleUnitType(SGCommonProto.E_BATTLE_UNIT.BATTLE_UNIT_MASTER);
            String masterName = names.length == 0 || Utils.isNull(names[0]) ? masterController.getName() : names[0];
            baseInfo.setNickName(masterName);
        }
        else if(sprite instanceof SoldierConfig)
        {
            data.setBattleUnitType(SGCommonProto.E_BATTLE_UNIT.BATTLE_UNIT_SOLDIER);
            baseInfo.setNickName(sprite.getName());
        }
        else
        {
            data.setBattleUnitType(SGCommonProto.E_BATTLE_UNIT.BATTLE_UNIT_STATIC_NPC);//暂时这样写
            baseInfo.setNickName("");
        }

        baseInfo.setLv(lv);

        data.setPlayInfo(baseInfo);

        data.setUniqueId(uniqueId);
        data.setConfigId(sprite.id);
        data.setPos(position.parsePos());
        data.setTeamNo(teamNo);
        data.setMaxHP(maxHp);
        data.setHp(hp);

        return data;
    }

    public SGCommonProto.BattleUnit.Builder parseBattleUnit(SGCommonProto.PlayerBaseInfo baseInfo)
    {
        SGCommonProto.BattleUnit.Builder data = SGCommonProto.BattleUnit.newBuilder();

        data.setPlayInfo(baseInfo);

        if(sprite instanceof MasterConfig)
        {
            data.setBattleUnitType(SGCommonProto.E_BATTLE_UNIT.BATTLE_UNIT_MASTER);
        }
        else if(sprite instanceof SoldierConfig)
        {
            data.setBattleUnitType(SGCommonProto.E_BATTLE_UNIT.BATTLE_UNIT_SOLDIER);
        }
        else
        {
            data.setBattleUnitType(SGCommonProto.E_BATTLE_UNIT.BATTLE_UNIT_STATIC_NPC);//暂时这样写
        }

        data.setUniqueId(uniqueId);
        data.setConfigId(sprite.id);


        data.setTeamNo(teamNo);
        data.setMaxHP(maxHp);
        data.setHp(hp);

        return data;
    }

    public void setPosition(Position position)
    {
        boolean born = this.position == null;

        this.position = position;

        if(position == null)
        {
            objectBound.setCenter(null);
        }
        else
        {
            objectBound.setCenter(new AbsCoord((float)(position.x+Math.random()),(float)(position.y+Math.random())));

            battleController.setToAstarMap(this);
        }

        if(born)
        {
            this.bornPoint = position;
            bornRoute = position.y >= battleController.getAstar().getAstarMap().height>>1 ? ConstantFactory.ROUTE_TOP : ConstantFactory.ROUTE_BOTTOM;
        }
    }

    /**
     * 是否触发冲锋
     * @return
     */
    public boolean checkTriggerToAttack()
    {
        if(DataFactory.currentTime - atkTime >= 2000)
        {
            if(buffBox.isHaveToAttackBuff())
                return true;
        }
        return false;
    }

    /**
     * 对敌人造成的伤害增加
     * @param value
     */
    public void addDamage(long value)
    {
        this.damage += value;

        if(spriteTemp != null)
            spriteTemp.setToEnemyDamage(damage);
    }

    public SGCommonProto.DamageObject parseDamage()
    {
        SGCommonProto.DamageObject.Builder damageObj = SGCommonProto.DamageObject.newBuilder();
        damageObj.setTeamNo(teamNo);
        damageObj.setId(getConfigId());
        damageObj.setValue(damage);
        return damageObj.build();
    }

    /**
     * 初始化主将技能时间
     * @param time
     */
    public void initSkillReleaseTime(long time)
    {
        if(defaultSkill != null)
            defaultSkill.releaseTime = time;

        for(BattleSkill battleSkill : skills)
        {
            battleSkill.releaseTime = time;
        }
    }


    public int getHPRate()
    {
        return (int) ((double) hp / maxHp * 100);
    }


    public int getUniqueId()
    {
        return uniqueId;
    }

    public String getName()
    {
        return sprite.name;
    }

    public Sprite getSprite()
    {
        return sprite;
    }

    public int getUnitType(){
        return sprite.unitType;
    }


    public void setStatus(E_BattleAObjectStatus status) {
        this.status = status;
    }

    public E_BattleAObjectStatus getStatus() {
        return status;
    }

    public boolean isDie()
    {
        return hp <= 0;
    }

    public boolean isFree() {
        return isFree;
    }

    public void setFree(boolean isFree) {
        this.isFree = isFree;
    }


    public long getHp() {
        return hp;
    }

    public void setHp(int hp) {
        this.hp = hp;
    }

    public int getTeamNo() {
        return teamNo;
    }

    public void setTeamNo(int teamNo) {
        this.teamNo = teamNo;
    }

    public Position getPosition() {
        return position;
    }

    public long getMaxHp() {
        return maxHp;
    }

    public int getConfigId()
    {
        return sprite.id;
    }

    public long getAtkTime() {
        return atkTime;
    }

    public void setAtkTime(long atkTime) {
        this.atkTime = atkTime;
    }

    public ObjectBound getObjectBound() {
        return objectBound;
    }

    public void setObjectBound(ObjectBound objectBound) {
        this.objectBound = objectBound;
    }

    public boolean isInitObject() {
        return isInitObject;
    }

    public void setInitObject(boolean isInitObject) {
        this.isInitObject = isInitObject;
    }

    private String getSkillInfo()
    {
        StringBuilder result = new StringBuilder();
        for(BattleSkill battleSkill : skills)
        {
            result.append(battleSkill.baseInfo());
            result.append("\n");
        }
        return result.length() > 0 ? result.substring(0, result.length()-1) : "";
    }


    public SpriteTemp getSpriteTemp()
    {
        return spriteTemp;
    }

    public void setSpriteTemp(SpriteTemp spriteTemp) {
        this.spriteTemp = spriteTemp;
    }

    public int getLv() {
        return lv;
    }

    public long getDamage() {
        return damage;
    }

    public int getStar() {
        return star;
    }

    public int getFc() {
        return fc;
    }

    public String baseInfo()
    {
        return "{" +
                "unique=" + uniqueId +
                ",id=" + sprite.id +
                ",name=" + getName() +
                ",teamNo=" + teamNo +
                ",position=" + position +
                ",lv=" + lv +
                ",status=" + status +
                "} ";
    }


    public String detailInfo() {
        return "{" +
                "unique=" + uniqueId +
                ",id=" + sprite.id +
                ",name=" + getName() +
                ",teamNo=" + teamNo +
                ",lv=" + lv +
                ",position=" + position +
                ",moveSpeed=" + moveSpeed +
                ",attackSpeed=" + attackSpeed +
                ",hp=" + hp + "/" + maxHp +
                ",atk=" + atk +
                ",def=" + def +
                ",cri=" + cri +
                ",rec=" + rec +
                ",add=" + add +
                ",exd=" + exd +
                ",hit=" + hit +
                ",eva=" + eva +
                ",power=" + power +
                ",wisdom=" + wisdom +
                ",agility=" + agility +
                ",defaultSkill={" + defaultSkill.baseInfo() + "}" +
                ",skills={" + getSkillInfo() + "}" +
                "} ";
    }

    @Override
    public String toString() {
        return baseInfo();
    }


}
